package org.graduation.rbac.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.graduation.common.NoPermissionException;
import org.graduation.feignapi.ProjectClient;
import org.graduation.model.common.RBAC.Permissions;
import org.graduation.model.common.RBAC.RolePermission;
import org.graduation.model.common.RBAC.Roles;
import org.graduation.model.common.RBAC.UserPermission;
import org.graduation.model.common.ResponseResult;
import org.graduation.model.common.project.Project;
import org.graduation.rbac.mapper.QueryWrapperFactory;
import org.graduation.rbac.mapper.RolePermissionMapper;
import org.graduation.rbac.mapper.UserPermissionMapper;
import org.graduation.rbac.service.UserPermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class UserPermissionServiceImpl extends ServiceImpl<UserPermissionMapper, UserPermission> implements UserPermissionService {

    @Autowired
    private ProjectClient projectClient;
    @Autowired
    private UserPermissionMapper userPermissionMapper;
    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Override
    public ResponseResult designateAdmin(Long pId, Integer owner, Integer uid) {
        Project project = (Project) projectClient.info(pId).getData();
        if (!owner.equals(project.getOwner())) {
            throw new NoPermissionException(Permissions.DESIGNATE_ADMIN);
        }
        boolean existAdmin = userPermissionMapper.exists(QueryWrapperFactory.existAdmin(pId, uid));
        if (!existAdmin) {
            userPermissionMapper.insert(new UserPermission(uid, Roles.ADMIN.getRoleId(), pId));
        }
        return ResponseResult.success();
    }

    @Override
    public ResponseResult revokeAdmin(Long pId, Integer owner, Integer adminUid) {
        Project project = (Project) projectClient.info(pId).getData();
        if (!owner.equals(project.getOwner())) {
            throw new NoPermissionException(Permissions.REVOKE_ADMIN);
        }
        boolean existAdmin = userPermissionMapper.exists(QueryWrapperFactory.existAdmin(pId, adminUid));
        if (existAdmin) {
            userPermissionMapper.deleteById(new UserPermission(adminUid, Roles.ADMIN.getRoleId(), pId));
        }
        return ResponseResult.success();
    }

    @Override
    public Set<Permissions> getUserAllPermissions(Long pId, Integer uid) {
        UserPermission userPermission = userPermissionMapper.selectOne(QueryWrapperFactory.getRole(pId, uid));
        List<RolePermission> permissions = rolePermissionMapper.selectList(QueryWrapperFactory.getRolePermissions(userPermission.getRoleId()));
        Set<Permissions> set = new HashSet<>();
        for (RolePermission rolePermission : permissions) {
            set.add(Permissions.valueOf(rolePermission.getPermissionId()));
        }
        return set;
    }

    @Override
    public ResponseResult checkPermission(Long pId, Integer uid, Permissions permissions) {
        if (getUserAllPermissions(pId, uid).contains(permissions)) {
            return ResponseResult.success();
        } else {
            throw new NoPermissionException(permissions);
        }
    }

    @Override
    public ResponseResult assignRole(Long pId, Integer uid, Roles role) {
        userPermissionMapper.insert(new UserPermission(uid, role.getRoleId(), pId));
        return ResponseResult.success();
    }

    @Override
    public ResponseResult revokeRoles(Long pId, Integer uid, Roles role) {
        userPermissionMapper.deleteById(new UserPermission(uid, role.getRoleId(), pId));
        return ResponseResult.success();
    }
}
